import paho.mqtt.client as mqtt
import json
import logging
import time
import os
import configparser
from datetime import datetime

# ------------------------ 配置管理 ------------------------
class ConfigManager:
    """统一管理所有配置参数"""
    def __init__(self):
        self.config = configparser.ConfigParser()
        with open('config.ini', encoding='utf-8') as f:  # 修复编码问题
            self.config.read_file(f)
        
    @property
    def mqtt_config(self) -> dict:
        return dict(self.config['MQTT'])
        
    @property
    def app_config(self) -> dict:
        return {
            'log_dir': self.config['APP']['LogDir']
        }

# ------------------------ 日志管理 ------------------------
class LogManager:
    """日志配置管理"""
    def __init__(self, log_dir: str):
        self.log_dir = log_dir
        self._ensure_directory()
        self.logger = self._configure_logger()
        
    def _ensure_directory(self):
        if not os.path.exists(self.log_dir):
            os.makedirs(self.log_dir)
            
    def _configure_logger(self):
        log_file = os.path.join(
            self.log_dir, 
            f"mqtt_monitor_{datetime.now().strftime('%Y%m%d')}.log"
        )
        
        logger = logging.getLogger('MQTTMonitor')
        logger.setLevel(logging.INFO)
        
        formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(message)s')
        
        # 文件日志 handler
        file_handler = logging.FileHandler(log_file)
        file_handler.setFormatter(formatter)
        
        # 控制台日志 handler
        console_handler = logging.StreamHandler()
        console_handler.setFormatter(formatter)
        
        logger.addHandler(file_handler)
        logger.addHandler(console_handler)
        
        return logger

# ------------------------ MQTT 客户端管理 ------------------------
class MQTTClientManager:
    """MQTT客户端管理"""
    def __init__(self, config: dict):
        self.client = mqtt.Client()
        self._configure_client(config)
        self._connected = False
        
    def _configure_client(self, config: dict):
        self.client.on_connect = self._on_connect
        self.client.on_message = self._on_message
        self.client.on_disconnect = self._on_disconnect
        
        # 设置自动重连参数
        self.client.reconnect_delay_set(min_delay=5, max_delay=60)
        
        # 设置连接参数
        if 'username' in config and 'password' in config:
            self.client.username_pw_set(
                config['username'],
                config['password']
            )
        
        # 异步连接
        self.client.connect_async(
            config['host'],
            int(config.get('port', 1883)),
            int(config.get('keepalive', 60))
        )
        
    def _on_connect(self, client, userdata, flags, rc):
        """连接回调函数"""
        self._connected = True
        if rc == mqtt.MQTT_ERR_SUCCESS:
            client.subscribe("yantan_fire_dev")
            logger.info("成功连接MQTT服务器，已订阅yantan_fire_dev主题")
        else:
            error_messages = {
                1: "协议版本错误",
                2: "客户端ID无效",
                3: "服务器不可用",
                4: "用户名密码错误",
                5: "未授权"
            }
            logger.error(f"连接失败: {error_messages.get(rc, '未知错误')}")

    def _on_disconnect(self, client, userdata, rc):
        """断开连接回调"""
        self._connected = False
        if rc != 0:
            logger.warning(f"意外断开连接，正在尝试重连 (错误码: {rc})")

    def _on_message(self, client, userdata, msg):
        try:
            payload = msg.payload
            payload = str(payload)
            # print(payload)
            devices = {'ABCD'}
            device = payload[2:6]
            if device not in devices:
                return
            anchorid = payload[6:10]
            # anchorids = {'0505'}
            # if anchorid not in anchorids:
            #     return
            rssi = payload[16:18]
            try:
                # 十六进制转十进制
                rssi_dec = int(rssi, 16)
                # 转换为有符号数值（关键算法）
                rssi = rssi_dec - 256 if rssi_dec >= 0x80 else rssi_dec        
            except ValueError as e:
                logger.error("RSSI格式错误: %s 原始值: %s", e, rssi)
                return    
            filtered_data = {
                "dev_id": device,
                "anchor_id": anchorid,
                "rssi": rssi  
            }
            # 记录日志并保存到 CSV
            logger.info(f"报警设备数据: {filtered_data}")

        except json.JSONDecodeError:
            logger.error("无效的JSON数据")
        except Exception as e:
            logger.error(f"处理错误: {str(e)}")
            
    def start(self):
        """启动客户端"""
        self.client.loop_start()
        
    def stop(self):
        """停止客户端"""
        self.client.disconnect()
        self.client.loop_stop()

# ------------------------ 主程序 ------------------------
if __name__ == "__main__":
    # 初始化配置
    config = ConfigManager()
    
    # 初始化日志
    log_manager = LogManager(config.app_config['log_dir'])
    logger = log_manager.logger
    
    try:
        # 创建MQTT客户端
        mqtt_client = MQTTClientManager(config.mqtt_config)
        
        # 显示启动信息
        print("\n" + "="*50)
        print(" MQTT消息监控系统启动 ")
        print(f"日志目录: {os.path.abspath(config.app_config['log_dir'])}")
        print("="*50 + "\n")
        
        # 启动客户端
        mqtt_client.start()
        
        # 保持主线程运行
        while True:
            time.sleep(1)
            
    except KeyboardInterrupt:
        logger.info("用户主动终止程序")
    except Exception as e:
        logger.critical(f"程序异常终止: {str(e)}")
    finally:
        mqtt_client.stop()
        logger.info("MQTT客户端已安全关闭")